#include "RegistroMemoria.h"

RegistroMemoria::RegistroMemoria(TipoMemoria tipo, int tamanio, void* accesoMemoria){
	this->tipoMemoria = tipo;
	this->tamanio = tamanio;
	this->p = accesoMemoria;
	this->dato = NULL;
	this->id = ComponenteAlmacenamiento::idSinAsignar;
}

RegistroMemoria::RegistroMemoria(TipoMemoria tipo, int tamanio, void* accesoMemoria, Dato *dato){
	this->tipoMemoria = tipo;
	this->tamanio = tamanio;
	this->p = accesoMemoria;
	this->dato = dato;
	this->id = ComponenteAlmacenamiento::idSinAsignar;
}

void RegistroMemoria::getAccesoDato(void **accesoDato){
	*accesoDato = this->p;
}

void RegistroMemoria::leer(Dato *datoLeido, TipoSerializacion modo){
	if(this->p==NULL)
		throw new NullPointerException();
	int bytesDato = this->tamanio;
	void *pos;
	pos = this->p;
	void *verificacion;
	if(this->tipoMemoria!=FIJA){
		verificacion = memmove(&bytesDato, this->p, Registro::bytesControlTamanio);
		if(verificacion!=(void*)&bytesDato)
			throw new MemoryStorageException(StorageException::lectura);
		pos = (char*) this->p + Registro::bytesControlTamanio;
	}
	void* miDato;
	miDato = malloc(bytesDato);
	verificacion = memmove(miDato,pos,bytesDato);	
	if(this->tipoMemoria!=FIJA)
		this->tamanio += Registro::bytesControlTamanio;
	datoLeido->unserialize(miDato, modo);
	free(miDato);	
}

void RegistroMemoria::escribir(void *accesoMemoria, TipoSerializacion modo){
	if(accesoMemoria==NULL)
		throw new NullPointerException();
	this->p = accesoMemoria;
	this->escribirEnMemoria(modo);
}

void RegistroMemoria::escribir(TipoSerializacion modo){
	this->escribirEnMemoria(modo);
}

void RegistroMemoria::escribir(void *accesoMemoria, Dato *dato, TipoSerializacion modo){
	if(accesoMemoria==NULL)
		throw new NullPointerException();
	this->dato = dato;
	this->tamanio = this->dato->getTamanio(modo) + Registro::bytesControlTamanio;
	this->escribirEnMemoria(modo);
}

void RegistroMemoria::borrar(){	
	if(this->p==NULL)
		throw new NullPointerException();
	free(this->dato);
	this->dato = NULL;
}

void RegistroMemoria::escribirEnMemoria(TipoSerializacion modo){
	void *verificacion;
	void *pos;
	pos = this->p;
	if(this->tipoMemoria!=FIJA){
		int datosAEscribir = this->dato->getTamanio(modo);
		verificacion = memmove(this->p, &datosAEscribir, Registro::bytesControlTamanio);
		if(verificacion!=this->p);
			throw new MemoryStorageException(StorageException::escritura);
		pos = (char*) this->p + Registro::bytesControlTamanio;
	}
	void *datoAEscribir=NULL;
	datoAEscribir = malloc(this->dato->getTamanio(modo));
	this->dato->serialize(&datoAEscribir, modo);
	verificacion = memmove(pos,datoAEscribir,this->dato->getTamanio(modo));
	if(verificacion!=this->p)
		throw new MemoryStorageException(StorageException::escritura);
	free(datoAEscribir);
}
